package codemaster.dao;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import codemaster.core.Constant;
import codemaster.core.Helper;
import codemaster.core.Master;

import com.Ostermiller.util.ExcelCSVParser;

import common.util.FileUtility;
import common.util.StringUtility;

public class DaoImplBuilder {
	private static final String[] imports = {};
	
	public String getPK(String[][] table)
	{
		String pk = null;
		for (int i = 3; i < table.length; i++) 
		{
			if (table[i][Constant.C_PRIMARY_KEY].trim()
					.equalsIgnoreCase(Constant.YES))
					{
						if (pk == null)
						pk = table[i][Constant.C_NAME];
						else
							pk = pk + "," + table[i][Constant.C_NAME];
					}
		}
		return pk;
	}
	
	public String getPK2(String[][] table)
	{
		String pk = null;
		for (int i = 3; i < table.length; i++) 
		{
			if (table[i][Constant.C_PRIMARY_KEY].trim()
					.equalsIgnoreCase(Constant.YES))
					{
						if (pk == null)
						pk = table[i][Constant.C_JAVA_TYPE]+" "+table[i][Constant.C_NAME];
						else
							pk = pk + "," + table[i][Constant.C_JAVA_TYPE]+" "+table[i][Constant.C_NAME];
					}
		}
		return pk;
	}
	
	class IndexInfo
	{
		String indexName;
		List<String> columnNames = new ArrayList<String>();
		List<String> columnTypes = new ArrayList<String>();
		boolean isUnique;
		
		String getIndexString()
		{
			String columnNamesString = null;
			for(int i =0; i < columnNames.size(); i++)
			{
				if(columnNamesString == null)
				{
					columnNamesString = columnNames.get(i);
				}
				else
				{
					columnNamesString = columnNamesString + "," + columnNames.get(i);
				}
			}
			
			return columnNamesString;
		}
		
		String getIndexString2()
		{
			String columnNamesString = null;
			for(int i =0; i < columnNames.size(); i++)
			{
				if(columnNamesString == null)
				{
					columnNamesString = columnTypes.get(i) + " " + columnNames.get(i);
				}
				else
				{
					columnNamesString = columnNamesString + "," + columnTypes.get(i) + " " + columnNames.get(i);
				}
			}
			
			return columnNamesString;
		}
		
	}
	
	public Map<String, IndexInfo> getIndex(String[][] table)
	{
		Map<String, IndexInfo> indexInfos = new HashMap<String, DaoImplBuilder.IndexInfo>();
		for (int i = 3; i < table.length; i++) 
		{
			String indexName = table[i][Constant.C_INDEX].trim();
			if (indexName.isEmpty() == false)
			{
				IndexInfo indexInfo = indexInfos.get(indexName);
				
				if (indexInfo == null)
				{
					indexInfo = new IndexInfo();
				    indexInfos.put(indexName, indexInfo);
				}
				indexInfo.indexName = table[i][Constant.C_INDEX].trim();
				indexInfo.isUnique = table[i][Constant.C_INDEX_ISUNIQUE].trim().isEmpty() ? false : true;
				indexInfo.columnNames.add(table[i][Constant.C_NAME]);
				indexInfo.columnTypes.add(table[i][Constant.C_JAVA_TYPE]);
			}
		}
		return indexInfos;
	}

	/**
	 * Builds a domain object class file
	 * 
	 * @param header
	 *            File header
	 * @param inputFile
	 *            the input file
	 * @param outputDir
	 *            the output directory
	 * @param packageName
	 *            the package name
	 */
	public void build(String header, File inputFile, File outputDir,
			String packageName) {
		// Determines the class name from the input file name
		String className = "I"+StringUtility.toTitleCase(FileUtility
				.getFileNameWithoutExtension(inputFile))
				+ "Dao";

		String varBeanName = FileUtility
		.getFileNameWithoutExtension(inputFile);
		String beanName = StringUtility.toTitleCase(FileUtility
				.getFileNameWithoutExtension(inputFile));

		BufferedWriter bfw = null;
		BufferedReader bfr = null;
		try {
			// Reads domain object attributes
			bfr = new BufferedReader(new FileReader(inputFile));
			String[][] table = ExcelCSVParser.parse(bfr);
			bfr.close();
			
			Map<String, IndexInfo> indexInfos = getIndex(table);

			// Creates the file at the destination folder
			String packageDir = Helper.getPackageDir(outputDir, packageName);
			(new File(packageDir)).mkdirs();
			bfw = new BufferedWriter(new FileWriter(packageDir + File.separator
					+ className + ".java"));
			

			// Write header
			header = header.replaceAll("<class>", className);
			bfw.write(header);

			// Writes package
			bfw.write("package " + packageName + ";\n");
			bfw.write("\n");
			
			
			bfw.write("import java.util.List;\n");
			bfw.write("import java.util.Map;\n");
			bfw.write("import com.game.core.dbcs.daoproxy.IDaoExecutor"+";\n");
			bfw.write("import com.game.core.dbcs.executor.DAOInfo"+";\n");
			bfw.write("import "+Master.props.getProperty("package.bean")+"."+beanName+";\n");
			
			// Writes class
			bfw.write("/**\n");
			bfw.write(" * dao Interface for " + className + "\n");
			bfw.write(" *\n");
			// TODO: Add code master version property
			bfw.write(" * @author CodeMaster v1.0\n");
			bfw.write(" */\n");
			bfw.write("public interface " + className
					+ " extends IDaoExecutor\n");
			bfw.write("{\n");
			
			

			// Writes default methods
			bfw.write("\t@DAOInfo(Params = \""+getPK(table)+"\")\n");
			bfw.write("\tpublic "+beanName+" select"+beanName+"("+getPK2(table)+");\n\n");
			
			for(IndexInfo indexInfo : indexInfos.values())
			{
				bfw.write("\t@DAOInfo(Params = \""+indexInfo.getIndexString()+"\")\n");
				if(indexInfo.isUnique)
				{
					bfw.write("\tpublic "+beanName+" select"+beanName+"By"+indexInfo.indexName+"("+indexInfo.getIndexString2()+");\n\n");
				}
				else
				{
					bfw.write("\tpublic List<"+beanName+"> select"+beanName+"ListBy"+indexInfo.indexName+"("+indexInfo.getIndexString2()+");\n\n");
				}
			}
			
			bfw.write("\t@DAOInfo(Params = \"\")\n");
			bfw.write("\tpublic List<"+beanName+"> select"+beanName+"List();\n\n");
			bfw.write("\t@DAOInfo(Params = \"\")\n");
			bfw.write("\tpublic Integer insert"+beanName+"("+beanName+" "+varBeanName+");\n\n");
			bfw.write("\t@DAOInfo(Params = \"\")\n");
			bfw.write("\tpublic "+"Integer"+" update"+beanName+"("+beanName+" "+varBeanName+");\n\n");
			bfw.write("\t@DAOInfo(Params = \"\")\n");
			bfw.write("\tpublic "+"Integer"+" delete"+beanName+"("+beanName+" "+varBeanName+");\n\n");
			
			bfw.write("}");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bfw != null) {
				try {
					bfw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}
}
